using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using AppScan;
using AppScan.Configuration;

/*
 * This product includes software developed by IBM Corporation (www.ibm.com).
 * All use and distribution of the IBM developed software is subject to Version 2.0
 * of the Apache License (http://www.apache.org/licenses/LICENSE-2.0).
 */

namespace PrivilegeEscalationRunnerExtension
{
	public partial class PrivilegeEscalationForm : Form
	{
		public PrivilegeEscalationRunnerExtension.LogMessageHandler logMsgHandler;
		public PrivilegeEscalationRunnerExtension.StepCompleteHandler stepCompleteHandler;
		public PrivilegeEscalationRunnerExtension.RunCompleteHandler runCompleteHandler;

		PrivilegeEscalationRunnerExtension _extension;
		private Thread _runThread = null;
		private StringBuilder _curLogText = new StringBuilder();

		public PrivilegeEscalationForm(PrivilegeEscalationRunnerExtension extension)
		{
			InitializeComponent();

			_extension = extension;

			logMsgHandler = new PrivilegeEscalationRunnerExtension.LogMessageHandler(this.LogMessageHandler);
			stepCompleteHandler = new PrivilegeEscalationRunnerExtension.StepCompleteHandler(this.StepCompleteHandler);
			runCompleteHandler = new PrivilegeEscalationRunnerExtension.RunCompleteHandler(this.RunCompleteHandler);
		}

		#region Event Handlers

		public void LogMessageHandler(string logMsg)
		{
			_curLogText.AppendLine(DateTime.Now.ToLongTimeString() + " : " + logMsg);
			ProgressTB.Text = _curLogText.ToString();
			ProgressTB.SelectionStart = _curLogText.Length;
			ProgressTB.ScrollToCaret();
		}

		private void StepCompleteHandler()
		{
			GeneralProgressBar.Value++;
		}

		private void RunCompleteHandler()
		{
			RunBtn.Enabled = true;
			CancelBtn.Enabled = true;
			PrivEscGroupBox.Enabled = true;
			SettingsGroupBox.Enabled = true;
		}

		#endregion

		#region Configuration Actions

		private void BrowseBtn_Click(object sender, EventArgs e)
		{
			if (PrimaryLoginFileTB.Text.Trim().Length > 0)
			{
				OpenLoginFileDialog.FileName = PrimaryLoginFileTB.Text;
			}

			DialogResult res = OpenLoginFileDialog.ShowDialog(this);
			if (res == DialogResult.OK)
			{
				PrimaryLoginFileTB.Text = OpenLoginFileDialog.FileName.Trim();
				FileInfo fi = new FileInfo(PrimaryLoginFileTB.Text);
				
				// Use the primary login file as an init for other traits
				if (ResultsFileTB.Text.Trim().Length == 0)
				{
					ResultsFileTB.Text = fi.DirectoryName + "\\" + fi.Name + ".PrivEsc.scan";
				}
				if (ScanFilesFolderTB.Text.Trim().Length == 0)
				{
					ScanFilesFolderTB.Text = fi.DirectoryName;
				}
			}
		}

		private void AddBtn_Click(object sender, EventArgs e)
		{
			DialogResult res = OpenLoginFileDialog.ShowDialog(this);
			if (res == DialogResult.OK)
			{
				string newFileName = OpenLoginFileDialog.FileName.Trim();
				if (LoginFilesList.Items.Contains(newFileName))
				{
					MessageBox.Show("File Name " + newFileName + " already exists");
				}
				else
				{
					LoginFilesList.Items.Add(newFileName);
				}
			}
		}

		private void RemoveBtn_Click(object sender, EventArgs e)
		{
			if (LoginFilesList.SelectedItem != null)
			{
				LoginFilesList.Items.Remove(LoginFilesList.SelectedItem);
			}
		}

		private void BrowseScanFolderBtn_Click(object sender, EventArgs e)
		{
			if (ScanFilesFolderTB.Text.Trim().Length > 0)
			{
				OpenScanFileFolerDialog.SelectedPath = ScanFilesFolderTB.Text;
			}

			DialogResult res = OpenScanFileFolerDialog.ShowDialog(this);
			if (res == DialogResult.OK)
			{
				ScanFilesFolderTB.Text = OpenScanFileFolerDialog.SelectedPath;
			}
		}

		private void ResultsFileBrowseBtn_Click(object sender, EventArgs e)
		{
			if (ResultsFileTB.Text.Trim().Length > 0)
			{
				OpenScanFileDialog.FileName = ResultsFileTB.Text;
			}

			DialogResult res = OpenScanFileDialog.ShowDialog(this);
			if (res == DialogResult.OK)
			{
				ResultsFileTB.Text = OpenScanFileDialog.FileName.Trim();
			}
		}

		private void BrowseScantBtn_Click(object sender, EventArgs e)
		{
			if (ConfigTemplateTB.Text.Trim().Length > 0)
			{
				OpenScantFileDialog.FileName = ConfigTemplateTB.Text;
			}

			DialogResult res = OpenScantFileDialog.ShowDialog(this);
			if (res == DialogResult.OK)
			{
				ConfigTemplateTB.Text = OpenScantFileDialog.FileName.Trim();
			}
		}

		private void CancelBtn_Click(object sender, EventArgs e)
		{
			DialogResult res = MessageBox.Show("Are you sure you want to cancel?", "Cancel Confirmation", MessageBoxButtons.YesNo);
			if (res == DialogResult.Yes)
			{
				this.DialogResult = DialogResult.Cancel;
				this.Close();
			}
		}
		#endregion

		public void RunBtn_Click(object sender, EventArgs e)
		{
			// Make sure we have at least one configuration item
			if (string.IsNullOrEmpty(ConfigTemplateTB.Text) || !File.Exists(ConfigTemplateTB.Text) ||
				string.IsNullOrEmpty(PrimaryLoginFileTB.Text) || !File.Exists(PrimaryLoginFileTB.Text) ||
				string.IsNullOrEmpty(ResultsFileTB.Text) || 
				string.IsNullOrEmpty(ScanFilesFolderTB.Text) || !Directory.Exists(ScanFilesFolderTB.Text))
			{
				MessageBox.Show("A valid config template file, primary login file, results file and scan files folder must be configured before running");
				return;
			}

			// Create the configuration
			_extension.Config.ConfigScanTemplate = ConfigTemplateTB.Text;
			_extension.Config.PrimaryLoginFileName = PrimaryLoginFileTB.Text;
			_extension.Config.OtherLoginFilesList = new List<string>();
			foreach (string loginFileName in LoginFilesList.Items)
				_extension.Config.OtherLoginFilesList.Add(loginFileName);
			_extension.Config.MaxUrlsPerScan = (int)MaxUrlsNumUpDown.Value;
			_extension.Config.ResultsScanFile = ResultsFileTB.Text;
			_extension.Config.ScanFilesFolder = ScanFilesFolderTB.Text;

			// Set the progress bar length to the number of steps.
			// Each scan is 3 steps (clear, explore, save), and the final priv esc testing & final save are 2 more.
			int nProgressItems = (1 /* non-auth scan */ + 1 /* primary */ + _extension.Config.OtherLoginFilesList.Count) * 3 + 2 /* priv esc testing and save */;
			GeneralProgressBar.Maximum = nProgressItems;
			GeneralProgressBar.Value = 0;

			RunBtn.Enabled = false;
			CancelBtn.Enabled = false;
			PrivEscGroupBox.Enabled = false;
			SettingsGroupBox.Enabled = false;

			_runThread = new Thread(new ThreadStart(_extension.StartRun));
			_runThread.SetApartmentState(ApartmentState.STA);
			_runThread.Start();
		}

		private void HelpBtn_Click(object sender, EventArgs e)
		{
			string helpText = File.ReadAllText(_extension.ExtensionsDir + "\\Readme.txt");
			MessageBox.Show(helpText);
		}
	}
}